<?php
/**
 * @ClassName: Wxlogin
 * @Description: TODO
 * @author: wyaohu
 * @Date: 2025-09-01 16:19
 * @Version: V1.0.0
 */

namespace app\api\controller;

use app\common\model;
use app\common\enum\UserStatus;
use app\common\logic\MemberLogic;
use app\common\logic\WechatLogic;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use think\Db;

class Wxlogin extends Api
{
    protected $first_leader = '';

    protected function initialize()
    {
        $this->first_leader = env('first_leader');
    }

    /**
     * 公众号登录
     * @return \think\response\Json
     */
    public function mpLogin()
    {
        $code = input('code', '');
        $invite_code = input('invite_code', $this->first_leader);
        $invite_type = input('invite_type', 0);
        $invite_store = input('invite_store', 0);

        $unionid = '';
        $openid = '';

        try {
            $session = (new WechatLogic())->getMpSessionCode($code);
        } catch (GuzzleException $e) {
            makelog("授权信息异常\n" . $e->getMessage(), 'api/login/mpLogin');
            return json(['code' => 0, 'msg' => '获取用户信息异常：' . $e->getMessage()]);
        }
        makelog("授权信息\n" . json_encode($session), 'api/login/mpLogin');
        if ($session['code'] === 1) {
            /*//获取用户信息
            $userInfo = $this->getUserInfo($session['access_token'], $session['openid']);
            makelog("用户信息\n" . json_encode($userInfo), 'api/login/mpLogin');*/
            if (isset($session['unionid'])) {
                $unionid = $session['unionid'];
            }
            if (isset($session['openid'])) {
                $openid = $session['openid'];
            }
            if (!$openid) {
                return json(['code' => 0, 'msg' => '登录失败']);
            }
            $invite_param = [
                'invite_id' => $invite_code,
                'invite_type' => $invite_type,
                'invite_store' => $invite_store,
            ];
            $res = $this->checkUser('wechat', $unionid, $openid, $invite_param, '');
            return json($res);
        } else {
            return json(['code' => 0, 'msg' => '登录失败']);
        }
    }

    /**
     * 小程序登录(手机号授权登录)
     * @return \think\response\Json
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function wxLogin()
    {
        // 获取code码
        $code = input('code');
        $iv = input('iv');
        $encryptedData = input('encryptedData');
        $inviter_id = input('inviter_id', $this->first_leader);
        $invite_type = input('invite_type', 0);
        $invite_store = input('invite_store', 0);
        $wechat_appid = env('wechat_appid');
        $wechat_appsecret = env('wechat_appsecret');
        $wxLoginUrl = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $wechat_appid . '&secret=' . $wechat_appsecret . '&js_code=' . $code . '&grant_type=authorization_code';
        // 获取微信授权url
        $url = sprintf($wxLoginUrl, $wechat_appid, $wechat_appsecret, $code);
        // 获取openid
        $client = new Client();
        $respone = $client->get($url);
        $body = $respone->getBody();
        $body = json_decode($body, true);
        if (!data_get($body, 'openid', '')) {
            // $this->error($body['errmsg']);
            return json(['code' => 0, 'msg' => $body['errmsg'], 'token' => '']);
        }
        $body['encryptedData'] = $encryptedData;
        $body['inviter_id'] = $inviter_id;
        $body['iv'] = $iv;
        $body['ip'] = requestIP();

        $unionid = '';
        $openid = '';

        makelog("微信登录\n" . json_encode($body), 'api/login/wxLogin');
        if (isset($body['unionid'])) {
            $unionid = $body['unionid'];
        }
        if (isset($body['openid'])) {
            $openid = $body['openid'];
        }
        if (!$openid) {
            return json(['code' => 0, 'msg' => '登录失败']);
        }
        $invite_param = [
            'inviter_id' => $inviter_id,
            'invite_type' => $invite_type,
            'invite_store' => $invite_store,
        ];
        $mobile = (new WechatLogic())->getPhone($iv, $encryptedData, $body['session_key']);
        $res = $this->checkUser('routine', $unionid, $openid, $invite_param, $mobile);
        return json($res);
    }

    /**
     * 小程序登录
     * @return \think\response\Json
     */
    public function miniLogin()
    {
        $code = input('code', '');
        $invite_code = input('invite_code', $this->first_leader);
        $invite_type = input('invite_type', 0);
        $invite_store = input('invite_store', 0);

        if (empty($code)) {
            $this->error('缺少必要参数');
        }

        try {
            $userinfo = WechatLogic::mini()->auth->session($code);
            makelog("小程序登录\n" . json_encode($userinfo), 'login/miniLogin');
            if (!$userinfo || !isset($userinfo['openid'])) {
                trace('微信登录失败');
                trace($userinfo);
                return json(['code' => 0, 'msg' => '微信登录失败']);
            }
            $openid = $userinfo['openid']; //用户的小程序 openID
            $unionid = $userinfo['unionid'] ?? '';

            $member = model('member')->where('mp_openid', $openid)->whereOr('unionid', $unionid)->find();

            if ($member) {
                $token = md5(requestIP() . time() . $member['id'] . mt_rand(100, 999));
                $updata = [
                    'token' => $token,
                    'last_login_time' => date_now(),
                    'last_login_ip' => requestIP(),
                    'errors' => 0,
                ];
                if ($unionid && !$member['unionid']) {
                    $updata['unionid'] = $unionid;
                }
                if (!$member['mp_openid']) {
                    $updata['mp_openid'] = $openid;
                }
                Db::name('member')->where('id', $member['id'])->update($updata);
                return json(['code' => 1, 'msg' => '登录成功', 'token' => $token]);
            } else {
                $invite_param = [
                    'inviter_id' => $invite_code,
                    'invite_type' => $invite_type,
                    'invite_store' => $invite_store,
                ];
                $res = $this->checkUser('routine', $unionid, $openid, $invite_param, '');
                return json($res);
            }
        } catch (\Exception $e) {
            trace('微信登录失败' . $e->getMessage());
            return json(['code' => 0, 'msg' => '微信登录失败']);
        }
    }

    /**
     * APP登录
     * @return \think\response\Json
     */
    public function appLogin()
    {
        $unionid = input('unionid');
        $openid = input('openid');
        $invite_code = input('invite_code', $this->first_leader);
        $invite_type = input('invite_type', 0);
        $invite_store = input('invite_store', 0);
        $log = "授权信息\n";
        $log .= "openid：" . $openid . "\n";
        $log .= "unionid：" . $unionid . "\n";
        makelog($log, 'api/login/appLogin');

        if (!$openid) {
            return json(['code' => 0, 'msg' => '登录失败']);
        }
        $invite_param = [
            'inviter_id' => $invite_code,
            'invite_type' => $invite_type,
            'invite_store' => $invite_store,
        ];
        $res = $this->checkUser('app', $unionid, $openid, $invite_param, '');
        return json($res);
    }

    /**
     * 检查用户是否存在
     * @param $loginType
     * @param $unionid
     * @param $openid
     * @param $invite_param
     * @param $mobile
     * @return array
     */
    private function checkUser($loginType, $unionid, $openid, $invite_param, $mobile = '')
    {
        $ip = requestIP();
        $log = "检查用户是否存在\n";
        $log .= "loginType：" . $loginType . "\n";
        $log .= "unionid：" . $unionid . "\n";
        $log .= "openid：" . $openid . "\n";
        $log .= "invite_code：" . $invite_param['inviter_id'] . "\n";
        $log .= "invite_type：" . $invite_param['invite_type'] . "\n";
        $log .= "invite_store：" . $invite_param['invite_store'] . "\n";
        $log .= "mobile：" . $mobile . "\n";
        $log .= "ip：" . $ip . "\n";
        makelog($log, 'api/login/checkUser');

        $updata = [
            'last_login_ip' => $ip,
            'last_login_time' => date("Y-m-d H:i:s"),
            'errors' => 0,
        ];

        $memberQuery = model\Member::where('status', 1);
        /*if ($mobile) {
            $memberQuery->where('mobile', $mobile);
        }*/
        if ($loginType === 'wechat') {
            // 公众号登录
            if ($unionid) {
                $condition_sql = "unionid = :unionid or mp_openid = :mp_openid";
                $memberQuery->whereRaw($condition_sql, ['unionid' => $unionid, 'mp_openid' => $openid]);
                $updata['unionid'] = $unionid;
            } else {
                $memberQuery->where('mp_openid', $openid);
            }
            $updata['mp_openid'] = $openid;
        } elseif ($loginType === 'routine') {
            // 小程序登录
            if ($unionid) {
                $condition_sql = "unionid = :unionid or openid = :openid";
//                var_dump($condition_sql);
                $memberQuery->whereRaw($condition_sql, ['unionid' => $unionid, 'openid' => $openid]);
                $updata['unionid'] = $unionid;
            } else {
                $memberQuery->where('openid', $openid);
            }
            $updata['openid'] = $openid;
        } else {
            // APP登录
            if ($unionid) {
                $condition_sql = "unionid = :unionid or app_openid = :app_openid";
                $memberQuery->whereRaw($condition_sql, ['unionid' => $unionid, 'app_openid' => $openid]);
                $updata['unionid'] = $unionid;
            } else {
                $memberQuery->where('app_openid', $openid);
            }
            $updata['app_openid'] = $openid;
        }

        $res = true;

        $member = $memberQuery->find();
        $sql = model\Member::getLastSql();
        makelog("获取用户信息sql\n" . $sql, 'api/login/checkUser');
        makelog("获取用户信息\n" . json_encode($member, 320), 'api/login/checkUser');

        if (!$member && $mobile) {
            $member = model\Member::where('mobile', $mobile)->find();
        }
        if ($member) {
            //获取token
            if ($member['token']) {
                $token = model\Member::where('id', $member['id'])->value('token');//token不变
            } else {
                $token = md5($ip . time() . $member['id'] . mt_rand(100, 999));
            }

            $updata['token'] = $token;

            makelog("更新信息\n" . json_encode($updata), 'api/login/checkUser');
            $res = model\Member::where('id', $member['id'])->update($updata);
        } else {
            //注册并获取token
            $arr = passCrypt();
            if (!$mobile) {
                $mobile = time() . rand(0, 9);
            }

            $add_data = [
                'password' => $arr[0],
                'salt' => $arr[1],
                'mobile' => $mobile,
                'username' => $mobile,
                'nickname' => env('app_name') . mt_rand(100, 999),
                'last_login_ip' => $ip,
                'create_time' => date("Y-m-d H:i:s"),
                'token' => '',
                'invite_type' => $invite_param['invite_type'],
                'invite_store' => $invite_param['invite_store'],
                'first_leader' => $invite_param['inviter_id'],
                'delete_time' => null,
                'status' => UserStatus::NORMAL,
                'unionid' => $unionid,
            ];

            if ($loginType === 'wechat') {
                // 公众号登录
                $add_data['mp_openid'] = $openid;
            } elseif ($loginType === 'routine') {
                // 小程序登录
                $add_data['openid'] = $openid;
            } else {
                // APP登录
                $add_data['app_openid'] = $openid;
            }
            // 添加一个会员
            $memberId = model\Member::insertGetId($add_data);
            $token = md5($ip . time() . $memberId . mt_rand(100, 999));

            $updata = [
                'last_login_ip' => $ip,
                'last_login_time' => date("Y-m-d H:i:s"),
                'token' => $token,
                'errors' => 0,
            ];
            $res = model\Member::where('id', $memberId)->update($updata);

            // 处理关系线
//            (new MemberLogic())->getJianjie(model\Member::get($memberId));
            (new MemberLogic())->setRelation(model\Member::get($memberId));

            // 赠送积分
//            LogignLogic::giveDot($memberId);
        }

        if ($res) {
            return ['code' => 1, 'msg' => '登录成功', 'token' => $token];
        } else {
            return ['code' => 0, 'msg' => '登录失败'];
        }
    }

}